# services/friend_service.py
import asyncio
from typing import List, Dict, Any
from datetime import datetime

from fastapi import Depends
from sqlalchemy.orm import Session

from common.sqlalchemy_db import SqlalchemyX
from common.util import singleton
from modules.User import User
from modules.mod import Friendship, Dialog, Message
from service.UserService import UserService


@singleton
class FriendService:
    def __init__(self, db: Session = SqlalchemyX.db_session() ):
        self.db = db
        self.user_service = UserService()
        self.session = SqlalchemyX().AsyncSessionLocal()

    async def get_friends_list(self, user_id: int) -> Dict[str, Any]:
        await self._check_user_exists(user_id)
        friends_ids = await self.get_all_friends_ids(user_id)
        friends_mess = await self.get_all_friends_mes(friends_ids)
        friends_list = self.classify_friends_by_char(friends_mess)

        return {
            "error_code": 0,
            "data": {
                "userId": user_id,
                "friendsCounts": len(friends_ids),
                "friendsList": friends_list
            }
        }

    async def _check_user_exists(self, user_id: int):
        user = self.db.query(User).filter(User.user_id == user_id).first()
        if not user:
            raise ValueError("用户不存在")
        return True

    async def get_all_friends_ids(self, user_id: int) -> List[int]:
        friendships = self.db.query(Friendship).filter(
            (Friendship.from_user_id == user_id) | (Friendship.to_user_id == user_id)
        ).all()

        friend_ids = []
        for f in friendships:
            if f.from_user_id == user_id:
                friend_ids.append(f.to_user_id)
            else:
                friend_ids.append(f.from_user_id)
        return friend_ids

    async def get_all_friends_mes(self, friend_ids: List[int]) -> List[Dict]:
        users = self.db.query(User).filter(User.user_id.in_(friend_ids)).all()
        return [
            {
                "user_id": u.user_id,
                "user_name": u.user_name,
                "user_avatar": u.user_avatar
            } for u in users
        ]

    def classify_friends_by_char(self, friends_mes: List[Dict]) -> Dict[str, List[Dict]]:
        friends_char_map = {}

        for friend in friends_mes:
            name = friend['user_name']
            first_letter = name[0].upper()
            if 'A' <= first_letter <= 'Z':
                key = first_letter
            else:
                key = '#'

            if key not in friends_char_map:
                friends_char_map[key] = []

            friends_char_map[key].append(friend)

        # 排序每个字母下的好友
        for key in friends_char_map:
            friends_char_map[key].sort(key=lambda x: x['user_name'])

        return friends_char_map

    async def add_friend(self, from_user_id: int, target_username: str) -> Dict:
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

        from_user = await self.user_service.get_user_basic_mes({"user_id": from_user_id})
        if not from_user:
            raise ValueError("发起者不存在")

        if from_user["user_name"] == target_username:
            raise ValueError("不能添加自己为好友")

        target_user = await self.user_service.get_user_basic_mes({"user_name": target_username})
        if not target_user:
            raise ValueError("目标用户不存在")

        if await self.check_add_friend_permission(from_user_id, target_user["user_id"]) and \
           await self.check_add_friend_permission(target_user["user_id"], from_user_id):

            # 已经可以互相加好友，直接建立双向关系
            friendship1 = Friendship(
                from_user_id=from_user_id,
                to_user_id=target_user["user_id"],
                add_friend_time=now,
                agree_time=now,
                friendship_state=1,
                friendship_type=0,
                top_if=0

            )
            # friendship2 = Friendship(
            #     from_user_id=target_user["user_id"],
            #     to_user_id=from_user_id,
            #     add_friend_time=now,
            #     agree_time=now,
            # )

            self.session.add(friendship1)
            # self.db.add(friendship2)

            messageFrom = Message()
            messageFrom.message_from_id = from_user_id
            messageFrom.message_to_id = target_user["user_id"]
            messageFrom.message_type = 0
            messageFrom.message_content = "U2FsdGVkX1/UUVzILjtGeDJvVPmhrDJfGCgknXEeTdu+HCtYhVP6S7XFvmfLkxcz"
            messageFrom.message_content_type = "text"
            messageFrom.message_created_time = now
            messageFrom.message_state = 1
            self.session.add(messageFrom)

            messageTo = Message()
            messageTo.message_from_id = target_user["user_id"]
            messageTo.message_to_id = from_user_id
            messageTo.message_type = 0
            messageTo.message_content = "U2FsdGVkX1/PCmhpCi0jRiGRC6WbAs15bNyobsIGEYLHBJQ7Ts7F0MxbZF4c5vqRXdjdOurGmOB13n39D1y6ng=="
            messageTo.message_content_type = "text"
            messageTo.message_created_time = now
            messageTo.message_state = 1
            self.session.add(messageTo)
            await self.session.commit()

            # 创建对话记录
            dialog1 = Dialog(
                dialog_from_id=from_user_id,
                dialog_target_id=target_user["user_id"],
                dialog_last_time=now,
                last_message_id = messageFrom.message_id
            )
            dialog2 = Dialog(
                dialog_from_id=target_user["user_id"],
                dialog_target_id=from_user_id,
                dialog_last_time=now,
                last_message_id=messageTo.message_id
            )
            self.session.add(dialog1)
            self.session.add(dialog2)
            await self.session.commit()
            await self.session.flush()

            return {
                "errorCode": 0,
                "data": {
                    "message": "你们已经是好友了，快来一起聊天吧",
                    "addFriendTime": now,
                    "agreeTime": now,
                    "fromUserId": from_user_id,
                    "fromUserName": from_user["user_name"],
                    "targetUserMes": {
                        "user_id": target_user["user_id"],
                        "username": target_user["user_name"],
                        "avatar": target_user["user_avatar"]
                    }
                }
            }
        return {"errorCode": 1, "message": "无法添加好友"}

    async def check_add_friend_permission(self, from_user_id: int, user_id: int) -> bool:
        friendship = self.db.query(Friendship).filter(
            Friendship.from_user_id == from_user_id,
            Friendship.to_user_id == user_id
        ).first()

        if not friendship:
            return True
        elif friendship.friendship_state == 2:  # 被拒绝过
            return True
        return False

    async def agree_friend(self, from_user_id: int, target_user_id: int, agreed: bool) -> Dict:
        now = datetime.utcnow()
        friendship = self.db.query(Friendship).filter(
            Friendship.from_user_id == target_user_id,
            Friendship.to_user_id == from_user_id
        ).first()

        if not friendship:
            raise ValueError("没有找到对应的好友申请")

        friendship.agree_time = now
        friendship.state = 1 if agreed else 2
        self.db.commit()

        if agreed:
            # 双向创建好友关系
            mutual_friendship = Friendship(
                from_user_id=from_user_id,
                to_user_id=target_user_id,
                add_time=now,
                agree_time=now,
                state=1,
                type=0
            )
            self.db.add(mutual_friendship)

            # 创建对话
            dialog1 = Dialog(
                from_user_id=from_user_id,
                target_user_id=target_user_id,
                last_time=now
            )
            dialog2 = Dialog(
                from_user_id=target_user_id,
                target_user_id=from_user_id,
                last_time=now
            )
            self.db.add(dialog1)
            self.db.add(dialog2)

            self.db.commit()

        return {
            "error_code": 0,
            "data": {
                "agreed": agreed,
                "agreeTime": now.isoformat(),
                "message": "已成功同意该好友请求" if agreed else "已成功拒绝该好友请求"
            }
        }